﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Npgsql;

namespace frmPrincipal
{
    public partial class frmInfoConsultas : Form
    {
        StandardDBConnection standardDBConnection = new StandardDBConnection();

        public enum Querys{
            MainSupplierByProduct,
            AttendantSales,
            MainSupplier,
            TopAttendants,
            SupplierByAverage
        }

        private Querys choosenQuery;
        private int cod_produto;
        private string dt_inicio;
        private string dt_fim;
        private int qtd_atendente;
        private int cod_atendente;
        private int callWidth;
        private int callHeight;

        private void ShowThis()
        {
            this.Show();
        }

        public frmInfoConsultas(Querys _choosenQuery, int callWidth, int callHeight)
        {
            choosenQuery = _choosenQuery;
            this.callWidth = callWidth;
            this.callHeight = callHeight;
            InitializeComponent();
        }

        private void frmInfoConsultas_Load(object sender, EventArgs e)
        {
            switch (choosenQuery)
            {
                case Querys.MainSupplierByProduct://qual forn fornece mais daquele produto?
                    PrepareFieldsQueryMainSupplierByProduct();
                    break;
                case Querys.AttendantSales://escolha de atendente?
                    PrepareFieldsQueryAttendantSales();
                    break;
                case Querys.MainSupplier://qual forn mais forneceu?
                    PrepareFieldsQueryMainSupplier();
                    break;
                case Querys.TopAttendants://quantos atendente serão listados?
                    PrepareFieldsQueryTopAttendants();
                    break;
                case Querys.SupplierByAverage://maior ou menor à média?
                    PrepareFieldsQuerySupplierByAverage();
                    break;
            }
        }


        //Funções Auxiliares de Preencher ComboBox
        private void Fill_cmbProduto(bool porCodigo)
        {
            NpgsqlCommand sqlCommand = new NpgsqlCommand();
            NpgsqlDataReader databaseDataReader;
            int codigo;
            string sqlCommandText = "SELECT cod_prod, nome_prod FROM produto ORDER BY ";
            string nome, aux;

            cmbProduto.Enabled = true;

            if (porCodigo)
            {
                sqlCommandText += "cod_prod";
                btnProdOrdNome.Enabled = true;
                btnProdOrdCodigo.Enabled = false;
            }
            else
            {
                sqlCommandText += "nome_prod";
                btnProdOrdCodigo.Enabled = true;
                btnProdOrdNome.Enabled = false;
            }

            sqlCommand.CommandType = CommandType.Text;
            sqlCommand.CommandText = sqlCommandText;
            sqlCommand.Connection = standardDBConnection.cnn;
            databaseDataReader = sqlCommand.ExecuteReader();

            cmbProduto.Items.Clear();

            while (databaseDataReader.HasRows)
            {
                databaseDataReader.Read();
                codigo = Convert.ToInt32(databaseDataReader["cod_prod"].ToString());
                nome = databaseDataReader["nome_prod"].ToString();
                aux = string.Format("{0:00000} - " + nome, codigo);
                cmbProduto.Items.Add(aux);
            }

            databaseDataReader.Close();
            databaseDataReader.Dispose();
            sqlCommand.Dispose();
        }
        private void Fill_cmbAttendant(bool porCodigo)
        {
            NpgsqlCommand sqlCommand = new NpgsqlCommand();
            NpgsqlDataReader databaseDataReader;
            int codigo;
            string sqlCommandText = "SELECT * FROM atendente ORDER BY ";
            string nome, aux;

            cmbAttendant.Enabled = true;

            if (porCodigo)
            {
                sqlCommandText += "cod_atend";
                btnAtendOrdNome.Enabled = true;
                btnAtendOrdCodigo.Enabled = false;
            }
            else
            {
                sqlCommandText += "nome_atend";
                btnAtendOrdCodigo.Enabled = true;
                btnAtendOrdNome.Enabled = false;
            }

            cmbAttendant.Items.Clear();

            sqlCommand.CommandType = CommandType.Text;
            sqlCommand.CommandText = sqlCommandText;
            sqlCommand.Connection = standardDBConnection.cnn;
            databaseDataReader = sqlCommand.ExecuteReader();

            cmbAttendant.Items.Add("00000 - Todos");

            while (databaseDataReader.HasRows)
            {
                databaseDataReader.Read();
                codigo = Convert.ToInt32(databaseDataReader["cod_atend"].ToString());
                nome = databaseDataReader["nome_atend"].ToString();
                aux = string.Format("{0:00000} - " + nome, codigo);
                cmbAttendant.Items.Add(aux);
            }

            databaseDataReader.Close();
            databaseDataReader.Dispose();
            sqlCommand.Dispose();
        }
        private void Fill_cmbMaiorMenor()
        {
            cmbMaiorMenor.Enabled = true;
            cmbMaiorMenor.Items.Add("acima");
            cmbMaiorMenor.Items.Add("abaixo");
        }

        //Preparação das Consultas
        private void PrepareFieldsQueryMainSupplierByProduct()
        {
            Fill_cmbProduto(true);
            dtpInicio.Enabled = true;
            dtpFim.Enabled = true;
        }
        private void PrepareFieldsQueryAttendantSales()
        {
            Fill_cmbAttendant(true);
        }
        private void PrepareFieldsQueryMainSupplier()
        {
            dtpInicio.Enabled = true;
            dtpFim.Enabled = true;
        }
        private void PrepareFieldsQueryTopAttendants()
        {
            txtAmountFuncionario.Enabled = true;
        }
        private void PrepareFieldsQuerySupplierByAverage()
        {
            Fill_cmbMaiorMenor();
        }

        //Teste das Consultas
        private bool CheckQueryFieldsMainSupplierByProduct()
        {
            bool ok = true;

            if (cmbProduto.SelectedIndex == -1)
            {
                ok = false;
                MessageBox.Show("Selecione um Produto!", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
            if (!ok)
                cmbProduto.BackColor = Color.LightBlue;
            else
                cmbProduto.BackColor = Color.White;

            ok = ok && CheckQueryFieldsMainSupplier();

            return ok;
        }
        private bool CheckQueryFieldsAttendantSales()
        {
            bool ok = true;

            if (cmbAttendant.SelectedIndex == -1)
            {
                ok = false;
                MessageBox.Show("Selecione um atendente!", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                cmbAttendant.BackColor = Color.LightBlue;
            }
            else
                cmbAttendant.BackColor = Color.White;
            return ok;
        }
        private bool CheckQueryFieldsMainSupplier()
        {
            bool ok = true;
            DateTime inicio, fim;

            inicio = DateTime.Parse(dtpInicio.Text);
            fim = DateTime.Parse(dtpFim.Text);
            if (DateTime.Compare(inicio, fim) > 0)
                ok = false;
            if (!ok)
            {
                MessageBox.Show("Data de início deve ser antes ou igual à data de fim!", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
                dtpInicio.BackColor = Color.LightBlue;
                dtpFim.BackColor = Color.LightBlue;
            }
            else
            {
                dtpInicio.BackColor = Color.White;
                dtpFim.BackColor = Color.White;
            }
            return ok;
        }
        private bool CheckQueryFieldsTopAttendants()
        {
            bool ok = true;
            int aux;
            if (!int.TryParse(txtAmountFuncionario.Text, out aux))
            {
                ok = false;
                MessageBox.Show("Verifique se você digitou um número inteiro positivo corretamente!", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
                txtAmountFuncionario.BackColor = Color.LightBlue;
            }
            else
                txtAmountFuncionario.BackColor = Color.White;
            return ok;
        }
        private bool CheckQueryFieldsSupplierByAverage()
        {
            bool ok = true;

            if (cmbMaiorMenor.SelectedIndex == -1)
            {
                ok = false;
                MessageBox.Show("Complete a frase!", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                cmbMaiorMenor.BackColor = Color.LightBlue;
            }
            else
                cmbMaiorMenor.BackColor = Color.White;
            return ok;
        }

        //Chama as Consultas
        private void CallQueryMainSupplierByProduct()
        {
            frmConEspecial consultaEspecial;
            string title, sqlCommandText, aux;

            aux = cmbProduto.Items[cmbProduto.SelectedIndex].ToString();
            this.cod_produto = Convert.ToInt32(aux.Substring(0, 5));

            this.dt_inicio = dtpInicio.Text;
            this.dt_fim = dtpFim.Text;

            title = "Consulta dos Fornecedores do Produto '" + aux.Substring(8, aux.Length - 8) + "' de " + this.dt_inicio + " a " + this.dt_fim;
            sqlCommandText = "SELECT nome_forn, tel_forn " +
                    "FROM fornecedor INNER JOIN fornece ON(cnpj = cnpj_forn) " +
                    "        INNER JOIN produto ON(cod_produto = cod_prod) " +
                    "WHERE cod_prod = " + cod_produto + " AND data BETWEEN '" + dt_inicio + "' AND '" + dt_fim + "' " +
                    "ORDER BY nome_forn ASC ";

            consultaEspecial = new frmConEspecial(title, sqlCommandText, callWidth, callHeight);
            this.Hide();
            
            consultaEspecial.Show();
            consultaEspecial.FormClosed += (closedSender, closedE) => ShowThis();
        }
        private void CallQueryAttendantSales()
        {
            frmConEspecial consultaEspecial;
            int selected_index = cmbAttendant.SelectedIndex;
            string title, sqlCommandText, aux;
            
            this.cod_atendente = Convert.ToInt32(cmbAttendant.Items[selected_index].ToString().Substring(0, 5));
            aux = cmbAttendant.Items[selected_index].ToString();

            sqlCommandText = "SELECT nome_atend, AVG(preco_venda) AS preco_medio, MAX(preco_venda) AS maior_preco, MIN(preco_venda) AS preco_minimo " +
                    "FROM contem INNER JOIN venda ON (contem.cod_venda = venda.cod_venda) " +
                    "            INNER JOIN atendente ON (cod_atendente = cod_atend) " +
                    "            INNER JOIN produto ON (cod_produto = cod_prod) " +
                    "GROUP BY cod_atend ";
            if (selected_index != 0)
            {
                sqlCommandText += "HAVING cod_atend = " + this.cod_atendente;
                title = "Consulta do(a) Attendant: " + aux.Substring(8, aux.Length - 8);
            }
            else
                title = "Consulta de Todos os Attendants";

            sqlCommandText += " ORDER BY AVG(preco_venda) DESC ";

            consultaEspecial = new frmConEspecial(title, sqlCommandText, callWidth, callHeight);
            this.Hide();
            consultaEspecial.Show();
            consultaEspecial.FormClosed += (closedSender, closedE) => ShowThis();
        }
        private void CallQueryMainSupplier()
        {
            frmConEspecial consultaEspecial;
            string title, sqlCommandText;
            
            this.dt_inicio = dtpInicio.Text;
            this.dt_fim = dtpFim.Text;

            title = "Consulta do Maior Fornecedor de " + this.dt_inicio + " até " + this.dt_fim + " em Valor (de custo) de Produtos";
            sqlCommandText = "SELECT a.nome_forn " +
                    "FROM (" +
                    "SELECT nome_forn, SUM(quantidade*preco_custo) AS total " +
                    "FROM produto INNER JOIN fornece  ON (cod_prod = cod_produto) INNER JOIN fornecedor ON (cnpj_forn = cnpj) " +
                    "GROUP BY fornecedor.nome_forn, cnpj_forn, data " +
                    "HAVING data BETWEEN '" + this.dt_inicio + "' AND '" + this.dt_fim + "'" +
                    ") a " +
                    "GROUP BY a.nome_forn, a.total " +
                    "HAVING a.total = MAX(a.total) " +
                    "ORDER BY nome_forn ASC ";

            consultaEspecial = new frmConEspecial(title, sqlCommandText, callWidth, callHeight);
            this.Hide();
            consultaEspecial.ShowDialog();
            consultaEspecial.FormClosed += (closedSender, closedE) => ShowThis();
        }
        private void CallQueryTopAttendants()
        {
            frmConEspecial consultaEspecial;
            string sqlCommandText, title;

            this.qtd_atendente = Convert.ToInt32(txtAmountFuncionario.Text);
            
            title = "Consulta dos "+this.qtd_atendente.ToString()+" Funcionários que mais Venderam em Valor";
            sqlCommandText = "SELECT nome_atend, cod_atend " +
                    "FROM ( " +
                    "   SELECT nome_atend, cod_atend, SUM(cod_produto) AS total " +
                    "   FROM atendente INNER JOIN venda ON (cod_atend = cod_atendente) " +
                    "                  INNER JOIN contem ON (venda.cod_venda = contem.cod_venda) " +
                    "   GROUP BY nome_atend, cod_atend " +
                    ") a " +
                    "GROUP BY nome_atend, cod_atend, total " +
                    //"HAVING a.total = MAX(a.total) " +
                    "ORDER BY a.total DESC " +
                    "LIMIT " + this.qtd_atendente.ToString();

            consultaEspecial = new frmConEspecial(title, sqlCommandText, callWidth, callHeight);
            this.Hide();
            consultaEspecial.ShowDialog();
            consultaEspecial.FormClosed += (closedSender, closedE) => ShowThis();
        }
        private void CallQuerySupplierByAverage()
        {
            frmConEspecial consultaEspecial;
            string title, sqlCommandText;

            title = "Consulta dos Fornecedores que Fornecem " + cmbMaiorMenor.Items[cmbMaiorMenor.SelectedIndex].ToString() + " da Média do Número de Produtos.";
            sqlCommandText = "SELECT nome_forn, cnpj " +
                    "FROM(" +
                    "SELECT nome_forn, cnpj, SUM(quantidade) AS quantidade " +
                    "FROM fornecedor INNER JOIN fornece ON (cnpj = cnpj_forn) " +
                    "GROUP BY cnpj, nome_forn " +
                    ") a " +
                    "GROUP BY nome_forn, cnpj, a.quantidade ";

            if (cmbMaiorMenor.SelectedIndex == 1)
                sqlCommandText += "HAVING a.quantidade <= AVG(a.quantidade) ";
            else
                sqlCommandText += "HAVING a.quantidade >= AVG(a.quantidade) ";

            sqlCommandText += "ORDER BY nome_forn ASC ";

            consultaEspecial = new frmConEspecial(title, sqlCommandText, callWidth, callHeight);
            this.Hide();
            consultaEspecial.ShowDialog();
            consultaEspecial.FormClosed += (closedSender, closedE) => ShowThis();
        }


        //Botões
        //Ordena Produtos Por Código
        private void btnProdOrdCodigo_Click(object sender, EventArgs e)
        {
            Fill_cmbProduto(true);
        }
        //Ordena Produtos Por Nome
        private void btnProdOrdNome_Click(object sender, EventArgs e)
        {
            Fill_cmbProduto(false);
        }
        //Ordena Attendants Por Código
        private void btnAtendOrdCodigo_Click(object sender, EventArgs e)
        {
            Fill_cmbAttendant(true);
        }
        //Ordena Attendants Por Nome
        private void btnAtendOrdNome_Click(object sender, EventArgs e)
        {
            Fill_cmbAttendant(false);
        }

        //Chamas as funções CallQuery
        private void btnSearch_Click(object sender, EventArgs e)
        {
            switch (choosenQuery)
            {
                case Querys.MainSupplierByProduct://qual forn fornece mais daquele produto?
                    if(CheckQueryFieldsMainSupplierByProduct())
                        CallQueryMainSupplierByProduct();
                    break;
                case Querys.AttendantSales://escolha de atendente?
                    if (CheckQueryFieldsAttendantSales())
                        CallQueryAttendantSales();
                    break;
                case Querys.MainSupplier://qual forn mais forneceu?
                    if (CheckQueryFieldsMainSupplier())
                        CallQueryMainSupplier();
                    break;
                case Querys.TopAttendants://quantos atendente serão listados?
                    if (CheckQueryFieldsTopAttendants())
                        CallQueryTopAttendants();
                    break;
                case Querys.SupplierByAverage://maior ou menor à média?
                    if (CheckQueryFieldsSupplierByAverage())
                        CallQuerySupplierByAverage();
                    break;
            }
        }

        //Volta p/ o formulário que o chamou
        private void btnReturn_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}
